package zookeeper

import (
	"encoding/json"
	"fmt"
	"github.com/go-zookeeper/zk"
	"log"
	"sync"
)

type Discovery struct {
	conn    *zk.Conn
	info    *NodeInfo
	manager *NodesManager
}

type NodesManager struct {
	sync.RWMutex
	// <serviceName,nodes>
	nodes map[string][]*NodeInfo
}

func NewDiscovery(conn *zk.Conn) *Discovery {
	return &Discovery{
		conn: conn,
		info: &NodeInfo{},
		manager: &NodesManager{
			nodes: make(map[string][]*NodeInfo),
		},
	}
}

func (d *Discovery) Watch() {

	//watcher := clientv3.NewWatcher(d.cli)
	//watchChan := watcher.Watch(context.Background(), "services/", clientv3.WithPrefix())
	//for {
	//	select {
	//	case resp := <-watchChan:
	//		d.watchEvent(resp.Events)
	//	}
	//}
}

func (d *Discovery) GetNode(svrName string) *NodeInfo {
	node := d.manager.GetNode(svrName)
	if node != nil {
		log.Printf("本地缓存找到node:%v\n", node)
		return node
	}
	svrKey := fmt.Sprintf("/%s/%s", "services", svrName)
	childKeys, _, err := d.conn.Children(svrKey)
	if err != nil {
		log.Printf("Discovery key:%v get children err:%+v\n", svrKey, err)
		return nil
	}
	for _, svrID := range childKeys {
		val, _, err := d.conn.Get(getRegKey(svrName, svrID))
		if err != nil {
			// handle error!
			log.Printf("zk get error %v\n", err)
			continue
		}
		newNode := &NodeInfo{}
		err = json.Unmarshal(val, newNode)
		newNode.SvrID = svrID
		if err != nil {
			log.Printf("Discovery json.Unmarshal err:%+v", err)
			continue
		}
		d.manager.AddNode(newNode)
		log.Printf("Discovery add newNode:%+v", newNode)
	}
	return d.manager.GetNode(svrName)
}
